#ifndef _VL_PROP__H_
#define _VL_PROP__H_

#include <memory>
#include <cstdint>
#include <string>
#include <functional>
#include <vector>
#include <map>
#include <set>

namespace VL {

// @Author: CimZzz
// @Date: 2023-03-14 12:03:48
// 预声明
class VLProp;
class VLPropReader;
class VLPropWriter;

#define vMap(...) std::initializer_list<std::pair<const std::string, VLProp>>({ __VA_ARGS__ })
#define vArr(...) std::initializer_list<VLProp>({ __VA_ARGS__ })

using VLPropArrayVistor = std::function<bool(VLProp& prop)>;
using VLPropMapVistor = std::function<bool(const std::string, VLProp& prop)>;

using VLPropError = int;
// @Author: CimZzz
// @Date: 2023-03-09 15:35:24
// 错误码定义

// 错误码 - 转型错误
static const VLPropError VL_PROP_ERROR_CAST = 0;
// 错误码 - 不支持的操作
static const VLPropError VL_PROP_ERROR_NOT_SUPPORT = 1;
// 错误码 - 数组越界
static const VLPropError VL_PROP_ERROR_OUT_BOUND = 2;
// 错误码 - 数组不支持容器类型
static const VLPropError VL_PROP_ERROR_ARR_TYPE = 3;
// 错误码 - 写入失败
static const VLPropError VL_PROP_ERROR_WRITE = 4;
// 错误码 - 读取单字节失败
static const VLPropError VL_PROP_ERROR_READ_OPEN = 5;
// 错误码 - 读取单字节失败
static const VLPropError VL_PROP_ERROR_READ_BYTE = 6;
// 错误码 - 读取字节缓存失败
static const VLPropError VL_PROP_ERROR_READ_BUF = 7;
// 错误码 - 读取到末尾
static const VLPropError VL_PROP_ERROR_READ_EOF = 8;
// 错误码 - 缩进错误
static const VLPropError VL_PROP_ERROR_READ_INDENT = 9;
// 错误码 - 冒号错误
static const VLPropError VL_PROP_ERROR_READ_COLON = 10;
// 错误码 - 没有找到冒号
static const VLPropError VL_PROP_ERROR_READ_NOT_FOUND_COLON = 11;
// 错误码 - 父级容器属性不为 Array
static const VLPropError VL_PROP_ERROR_READ_NOT_MATCH_ARRAY = 12;
// 错误码 - 父级容器属性不为 Map
static const VLPropError VL_PROP_ERROR_READ_NOT_MATCH_MAP = 13;
// 错误码 - 错误的模板定义
static const VLPropError VL_PROP_ERROR_READ_TEMPLATE_DEF = 14;
// 错误码 - 模板合并失败
static const VLPropError VL_PROP_ERROR_READ_TEMPLATE_COMBINE = 15;
// 错误码 - 错误的控制分支
static const VLPropError VL_PROP_ERROR_READ_CONTROL = 16;
// 错误码 - 触发错误指令
static const VLPropError VL_PROP_ERROR_READ_ERROR = 17;
// 错误码 - 错误的跨行配置
static const VLPropError VL_PROP_ERROR_READ_CROSS_LINE = 18; 
// 错误码 - 错误的文件引入
static const VLPropError VL_PROP_ERROR_READ_IMPORT = 19;
// 错误码 - 模板合并相互循环
static const VLPropError VL_PROP_ERROR_READ_TEMPLATE_LOOP = 20;

/**
 * @Author: CimZzz
 * @Date: 2023-03-09 15:34:51
 * 
 * 属性异常
 */
class VLPropExcetion {
public:
	explicit VLPropExcetion(int errorCode, const char * msg, ...);
	int errorCode;
	std::string message;
};

/**
 * @Author: CimZzz
 * @Date: 2023-03-08 18:42:50
 * 
 * 属性类型
 */
enum class VLPropType {
	// 空节点类型
	Empty,
	// 值类型
	Node,
	// 数组类型
	Array,
	// 映射表类型
	Map,
};

/**
 * @Author: CimZzz
 * @Date: 2023-03-08 19:05:37
 * 
 * 属性值类型
 */
enum class VLPropValueType {
	// 空值
	Void,
	// 字符串
	String,
	// 布尔值
	Boolean,
	// 字节
	Byte,
	// 无符号字节
	UByte,
	// 短整型
	Short,
	// 无符号短整型
	UShort,
	// 整数
	Int,
	// 无符号整数
	UInt,
	// 长整型
	Long,
	// 无符号长整型
	ULong,
	// 双精度浮点型
	Double,
};

/**
 * @Author: CimZzz
 * @Date: 2023-03-08 18:37:36
 * 
 * 属性基类
 */
class VLProp: public std::enable_shared_from_this<VLProp> {
public:
	// @Author: CimZzz
	// @Date: 2023-03-13 14:41:16
	// 构造方法
	VLProp();
	VLProp(std::initializer_list<std::pair<const std::string, VLProp>> props);
	VLProp(std::initializer_list<VLProp> props);
	VLProp(const bool& value);
	VLProp(const char * value);
	VLProp(const std::string& value);
	VLProp(const int8_t& value);
	VLProp(const uint8_t& value);
	VLProp(const int16_t& value);
	VLProp(const uint16_t& value);
	VLProp(const int32_t& value);
	VLProp(const uint32_t& value);
	VLProp(const int64_t& value);
	VLProp(const uint64_t& value);
	VLProp(const double& value);

	VLPropType getPropType() const;
	VLPropValueType getValueType() const;
	
	// @Author: CimZzz
	// @Date: 2023-03-13 15:37:28
	// 操作方法
	VLProp& operator [] (const std::string& key);
	VLProp& operator [] (size_t index);
	const VLProp& operator [] (const std::string& key) const;
	const VLProp& operator [] (size_t index) const;
	const bool operator == (const VLProp& prop) const;
	const bool checkValueEqual (const VLProp& prop) const;
	const bool operator != (const VLProp& prop) const;

	VLProp& add(const VLProp& prop);
	VLProp& insert(size_t index, const VLProp& prop);	
	void unique();
	void addComment(const std::string& comment);
	void addComments(const std::vector<std::string>& commentList);

	const bool boolValue() const;
	const std::string strValue() const;
	const int8_t byteValue() const;
	const uint8_t ubyteValue() const;
	const int16_t shortValue() const;
	const uint16_t ushortValue() const;
	const int32_t intValue() const;
	const uint32_t uintValue() const;
	const int64_t longValue() const;
	const uint64_t ulongValue() const;
	const double doubleValue() const;

	const bool boolValue(const bool& defaultValue) const;
	const std::string strValue(const std::string& defaultValue) const;
	const int8_t byteValue(const int8_t& defaultValue) const;
	const uint8_t ubyteValue(const uint8_t& defaultValue) const;
	const int16_t shortValue(const int16_t& defaultValue) const;
	const uint16_t ushortValue(const uint16_t& defaultValue) const;
	const int32_t intValue(const int32_t& defaultValue) const;
	const uint32_t uintValue(const uint32_t& defaultValue) const;
	const int64_t longValue(const int64_t& defaultValue) const;
	const uint64_t ulongValue(const uint64_t& defaultValue) const;
	const double doubleValue(const double& defaultValue) const;

	const bool isArray() const;
	const bool isMap() const;
	const bool isNode() const;
	const bool isEmpty() const;

	const size_t size() const;

	bool combine(const VLProp& prop, bool deepCombine = true);

	const void copy(VLProp& targetProp) const;

	const void visitArr(VLPropArrayVistor visitor) const;
	const void visitMap(VLPropMapVistor visitor) const;

	const void print() const;

	const void reset();

	const void writeVLC(VLPropWriter& writer) const;
	const void writeVLP(VLPropWriter& writer) const;
	static void readVLC(VLPropReader& reader, VLProp& prop);
	static void readVLP(VLPropReader& reader, VLProp& prop, const std::map<std::string, std::string>& constants = {}, const std::set<std::string>& featureSet = {});

	const void writeVLC(const std::string& filePath) const;
	const void writeVLP(const std::string& filePath) const;
	static void readVLC(const std::string& filePath, VLProp& prop);
	static void readVLP(const std::string& filePath, VLProp& prop, const std::map<std::string, std::string>& constants = {}, const std::set<std::string>& featureSet = {});

private:
	const bool _checkNodeEqual(const VLProp& prop) const;
	const bool _checkArrayEqual(const VLProp& prop) const;
	const bool _checkMapEqual(const VLProp& prop) const;

	const size_t _getArraySize() const;
	const size_t _getMapSize() const;

	const void _copyNode(VLProp& targetProp) const;
	const void _copyArray(VLProp& targetProp) const;
	const void _copyMap(VLProp& targetProp) const;

	void _uniqueArr();
	void _uniqueMap();

	const void _printNode(std::string margin) const;
	const void _printArray(std::string margin) const;
	const void _printMap(std::string margin) const;


	const void _writeVLC(VLPropWriter& writer) const;
	const void _writeNodeVLC(VLPropWriter& writer) const;
	const void _writeArrayVLC(VLPropWriter& writer) const;
	const void _writeMapVLC(VLPropWriter& writer) const;
	const void _writeEmptyVLC(VLPropWriter& writer) const;


	const void _readNodeVLC(VLPropReader& reader);
	const void _readArrayVLC(VLPropReader& reader);
	const void _readMapVLC(VLPropReader& reader);
	const void _readEmptyVLC(VLPropReader& reader);
	const void _readExtraVLC(VLPropReader& reader);

	const void _writeVLP(VLPropWriter& writer) const;
	const void _writeNodeVLP(VLPropWriter& writer, std::string margin) const;
	const void _writeArrayVLP(VLPropWriter& writer, std::string margin) const;
	const void _writeMapVLP(VLPropWriter& writer, std::string margin) const;

	static const char * _getValueTypeStr(VLPropValueType valueType);
	static const char * _getPropTypeStr(VLPropType propType);

	static VLProp emptyPtop;

	std::shared_ptr<void> dataPointer;
	std::shared_ptr<std::vector<std::string>> extraPointer;

	VLPropType type;
	VLPropValueType valueType;
};

};

#endif // _VL_PROP__H_
